package com.example.demo.controller;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.example.demo.config.MqttBroker;
import com.example.demo.entity.*;
import com.example.demo.service.*;
import com.example.demo.util.GetMessage;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/api/produce")
@RequiredArgsConstructor
@Component
public class ProducePlanController {
    @Value("${codeSystem.ip}")
    private String ip;
    private static final ObjectMapper objectMapper = new ObjectMapper();

    private final ProducePlanService producePlanService;
    private final CodeHistoryService codeHistoryService;
    private final PurchaseOrderService purchaseOrderService;
    private final SerialNumberService serialNumberService;

    private final PurchaseApplyOrderService purchaseApplyOrderService;
    private final TrainInfoService trainInfoService;
    private final UserProductinfoService userProductinfoService;
    private final CustomRulesService customRulesService;
    private final CodeAssignmentRulesService codeAssignmentRulesService;
    @CrossOrigin(origins ="*" ,maxAge = 3600)
    @PostMapping("/save1")
    public GetMessage insert (@RequestBody ProducePlan producePlan) throws JsonProcessingException, MqttException {
        producePlan.setPlantime(Util.getNowTime());
        String code=codeHistoryService.make(producePlan.getUserid(),"producePlan",producePlan.getTrainingid(),2,null,"MA.156.110116.1007/61.12000000.2501");
        producePlan.setIdentifycode(code);
        producePlan.setPlanstate("0");
        producePlan.setProducenumber("90");
        ProducePlan p=producePlanService.selectByInfo(producePlan.getUserid(),producePlan.getTrainingid(),null,producePlan.getOrdernumber(),null);
        if(p!=null){
            return new GetMessage("订单已排产","500","");

        }
        boolean bol=producePlanService.save(producePlan);
        if(bol){
            Map<String,Object> map=new HashMap<>();
            map.put("type","producePlan");
            map.put("trainingId",producePlan.getTrainingid());
            String payload = objectMapper.writeValueAsString(map);
            MqttBroker.mqttClient.publish("StepInfo/supply/"+producePlan.getUserid(),new MqttMessage(payload.getBytes(StandardCharsets.UTF_8)));
            return new GetMessage("成功","200","");
        }
        return new GetMessage("失败","500","");
    }

    public GetMessage addInfo(ProducePlan producePlan, String appId) throws JsonProcessingException, UnsupportedEncodingException {
        String model="GYL-SC";
        Map<String,Object> infoList=Util.getJsonStr(appId,model);
        ObjectMapper mapper = new ObjectMapper();
        String jsonString = mapper.writeValueAsString(infoList);
        TrainInfo trainInfo=trainInfoService.selectByUserId(producePlan.getUserid()).get(0);
        Map<String,String> headerList=new HashMap<>();
        headerList.put("X-Access-Key",trainInfo.getAccesskey());
        String code="";
        UserProductinfo userProductinfo=new UserProductinfo();
        UserProductinfo u=userProductinfoService.selectProductInfoOne(producePlan.getUserid(),appId,null);
        if(u==null){
            String res=Util.postUrl(ip+"/api/client/model",headerList,jsonString);
            JSONObject jsonResponse = new JSONObject(res);
            if(jsonResponse.get("code").equals("SUCCESS")){
                JSONObject jsonResponse1 = new JSONObject(jsonResponse.get("data"));
                code=jsonResponse1.get("code").toString();
                userProductinfo.setUserid(producePlan.getUserid());
                userProductinfo.setProductinfo("");
                userProductinfo.setAppid(appId);
                userProductinfo.setTrainingid(producePlan.getTrainingid());
                userProductinfo.setProductmodel(model);
                userProductinfo.setCategorycode(code);
                userProductinfo.setModelid(jsonResponse1.get("id").toString());
                userProductinfoService.save(userProductinfo);
                return new GetMessage("成功","200",code);
            }else{
                return new GetMessage(jsonResponse.get("message").toString(),"500",code);
            }

        }else{
            return new GetMessage("已新增产品"+u.getProductmodel(),"500",code);
        }
    }
    public GetMessage register(String userId,String appId) throws IOException {
        UserProductinfo userProductinfo=userProductinfoService.selectProductInfoOne(userId,appId,null);
        Map<String,String> headerList=new HashMap<>();
        TrainInfo trainInfo=trainInfoService.selectByUserId(userId).get(0);
        headerList.put("X-Access-Key",trainInfo.getAccesskey());
        String res=Util.putUrl(ip+"/api/client/model/"+userProductinfo.getModelid()+"/register",headerList);
        JSONObject jsonResponse = new JSONObject(res);
        if(jsonResponse.get("code").equals("SUCCESS")){
            JSONObject jsonResponse1 = new JSONObject(jsonResponse.get("data"));
            String code=jsonResponse1.get("code").toString();

            return new GetMessage("成功","200",code);
        }
        return new GetMessage(jsonResponse.get("message").toString(),"500","");
    }
    public GetMessage addCustom(String userId,String trainingId,String appId) throws JsonProcessingException {
        CustomRules customRules=new CustomRules();
        String name="自定义-生产计划";
        String rule="[datetime|yyyyMMddHHmmss].[random|4].[number|9999]";
        String ruleDesc="批次号.随机码.序列号";
        Map<String, Object> jsonMap = new HashMap<>();
        jsonMap.put("name", name);
        jsonMap.put("rule", rule);
        jsonMap.put("ruleDesc", ruleDesc);

        TrainInfo trainInfo=trainInfoService.selectByUserId(userId).get(0);
        Map<String,String> headerList=new HashMap<>();
        headerList.put("X-Access-Key",trainInfo.getAccesskey());
        ObjectMapper objectMapper = new ObjectMapper();
        String jsonString = objectMapper.writeValueAsString(jsonMap);
        String res=Util.postUrl(ip+"/api/client/custom-rule",headerList,jsonString);
        JSONObject jsonResponse = new JSONObject(res);
        if(jsonResponse.get("code").equals("SUCCESS")){
            JSONObject jsonResponse1 = new JSONObject(jsonResponse.get("data"));
            customRules.setRuleid(jsonResponse1.get("id"));
            customRules.setRulename(name);
            customRules.setRule(rule);
            customRules.setRuledesc(ruleDesc);
            customRules.setUserid(userId);
            customRules.setTrainingid(trainingId);
            customRules.setAppid(appId);
            boolean bol=customRulesService.save(customRules);
            if(bol){
                return new GetMessage("成功","200",customRules);
            }
        }

        return new GetMessage("失败","500",null);
    }
    public GetMessage addRule(String userId,String trainingId,String appId) throws JsonProcessingException {
        UserProductinfo userProductinfo=userProductinfoService.selectProductInfoOne(userId,appId,null);
//        CodeAssignmentRules codeAssignmentRules=codeAssignmentRulesService.select(userId,"purchaseOrder",trainingId,"0").get(0);
        CustomRules customRules=customRulesService.select(userId,appId,null).get(0);
        if(customRules==null){
            return new GetMessage("未找到自定义规则","500",null);
        }
        String name="生产计划";

        Map<String, Object> bjsonMap = new HashMap<>();
        bjsonMap.put("name", name);
        bjsonMap.put("modelId", userProductinfo.getModelid());
        bjsonMap.put("customRuleId", customRules.getRuleid());
        String bjsonString = objectMapper.writeValueAsString(bjsonMap);

        TrainInfo trainInfo=trainInfoService.selectByUserId(userId).get(0);
        Map<String,String> headerList=new HashMap<>();
        headerList.put("X-Access-Key",trainInfo.getAccesskey());
        String bres=Util.postUrl(ip+"/api/client/identification-code-rule",headerList,bjsonString);
        JSONObject bjsonResponse = new JSONObject(bres);
        if(!(bjsonResponse.get("code").equals("SUCCESS"))){
            return new GetMessage(bjsonResponse.get("message").toString(),"500",null);
        }

        JSONObject bdata = new JSONObject(bjsonResponse.get("data"));
        CodeAssignmentRules codeAssignmentRules=new CodeAssignmentRules();
        codeAssignmentRules.setRulename(name);
        codeAssignmentRules.setCodingid(customRules.getRuleid());
        codeAssignmentRules.setRuletype("0");
        codeAssignmentRules.setAppid(appId);
        codeAssignmentRules.setTrainingid(trainingId);
        codeAssignmentRules.setUserid(userId);
        codeAssignmentRules.setRuleid(bdata.get("id").toString());
        codeAssignmentRules.setCodetype("MA");
        codeAssignmentRules.setUserid(userId);
        boolean bol=codeAssignmentRulesService.save(codeAssignmentRules);
        if(bol){
            return new GetMessage("成功","200",codeAssignmentRules);
        }
        return new GetMessage("失败","500",null);
    }
    public GetMessage getCode(String userId,String trainingId,String appId,Integer ruleId) throws JsonProcessingException {
        String code="";
        TrainInfo trainInfo=trainInfoService.selectByUserId(userId).get(0);
        Map<String,String> headerList=new HashMap<>();
        headerList.put("X-Access-Key",trainInfo.getAccesskey());

        Map<String, Object> jsonMap = new HashMap<>();
        jsonMap.put("count", 1);

        CodeAssignmentRules codeAssignmentRules=codeAssignmentRulesService.selectById(ruleId);

        ObjectMapper objectMapper = new ObjectMapper();
        String jsonString = objectMapper.writeValueAsString(jsonMap);
        String res=Util.postUrl(ip+"/api/client/identification-code-record/"+codeAssignmentRules.getRuleid()+"/batch",headerList,jsonString);

        JSONObject jsonResponse = new JSONObject(res);
        if(jsonResponse.get("code").equals("SUCCESS")){
            JSONObject data = new JSONObject(jsonResponse.get("data"));
            JSONArray jsonArray=new JSONArray(data.get("codes"));
            code=jsonArray.get(0).toString();
            CodeHistory codeHistory=new CodeHistory();
            codeHistory.setCodeinfo(code);
            codeHistory.setRulesid(ruleId);
            codeHistory.setTrainingid(trainingId);
            codeHistory.setUserid(userId);
            codeHistory.setAppid(appId);
            codeHistory.setRuletype(1);
            codeHistoryService.save(codeHistory);

            return new GetMessage("成功","200",code);
        }
        return new GetMessage(jsonResponse.get("message").toString(),"500","");
    }
    @CrossOrigin(origins ="*" ,maxAge = 3600)
    @PostMapping("/save")
    public GetMessage save ( @RequestBody ProducePlan producePlan) throws IOException, MqttException {
        ProducePlan p=producePlanService.selectByInfo(null,null,null,producePlan.getOrdernumber(),null);
        if(p!=null){
            return new GetMessage("已添加生产计划","500","");
        }

        List<UserProductinfo> listUser=userProductinfoService.selectProductInfo(producePlan.getUserid(),"producePlan",null);
        if(listUser.size()==0){
            //新增型号
            GetMessage mes1=addInfo(producePlan,"producePlan");
            if(!(mes1.getCode().equals("200"))){
                return mes1;
            }
            //注册
            GetMessage mes2=register(producePlan.getUserid(),"producePlan");
            if(!(mes2.getCode().equals("200"))){
                return mes2;
            }
        }

        //添加规则
        List<CodeAssignmentRules> codeList=codeAssignmentRulesService.select(producePlan.getUserid(),"producePlan",null,"0");
        Integer id=0;
        if(codeList.size()==0){
            GetMessage mes3=addCustom(producePlan.getUserid(),producePlan.getTrainingid(),"producePlan");
            if(!(mes3.getCode().equals("200"))){
                return mes3;
            }
            GetMessage mes4=addRule(producePlan.getUserid(),producePlan.getTrainingid(),"producePlan");
            if(!(mes4.getCode().equals("200"))){

                return mes4;
            }
            CodeAssignmentRules codeAssignmentRules=(CodeAssignmentRules)mes4.getData();
            id = (Integer) (codeAssignmentRules.getId());
        }else{
            id= (Integer) (codeList.get(0).getId());
        }

        //赋码
        GetMessage mes5= getCode(producePlan.getUserid(),producePlan.getTrainingid(),"producePlan",id );
        if(!(mes5.getCode().equals("200"))){
            return mes5;
        }
        String code=mes5.getData().toString();
        producePlan.setPlantime(Util.getNowTime());
        producePlan.setIdentifycode(code);
        producePlan.setPlanstate("0");
        producePlan.setProducenumber("90");

        boolean bol=producePlanService.save(producePlan);
        if(bol){
            Map<String,Object> map=new HashMap<>();
            map.put("type","producePlan");
            map.put("trainingId",producePlan.getTrainingid());
            String payload = objectMapper.writeValueAsString(map);
            MqttBroker.mqttClient.publish("StepInfo/supply/"+producePlan.getUserid(),new MqttMessage(payload.getBytes(StandardCharsets.UTF_8)));
            return new GetMessage("成功","200","");
        }
        return new GetMessage("失败","500","");
    }


    @CrossOrigin(origins ="*" ,maxAge = 3600)
    @PostMapping("/updatebyid")
    public GetMessage updatebyid (@RequestBody ProducePlan producePlan) throws JsonProcessingException, MqttException {
        boolean bol=producePlanService.updateById(producePlan);
        if(bol){

            return new GetMessage("成功","200",producePlan);
        }
        return new GetMessage("失败","500","");
    }
    @CrossOrigin(origins ="*" ,maxAge = 3600)
    @GetMapping("/selectbyinfo")
    public GetMessage select ( String userId,String trainingId,String planNumber,String orderNumber,String identifyCode) throws JsonProcessingException, MqttException {
        ProducePlan producePlan=producePlanService.selectByInfo(userId,trainingId,planNumber,orderNumber,identifyCode);
        if(producePlan!=null){
            return new GetMessage("成功","200",producePlan);
        }
        return new GetMessage("失败","500","");
    }
    @CrossOrigin(origins ="*" ,maxAge = 3600)
    @GetMapping("/number")
    public GetMessage MakeNumber () throws JsonProcessingException, MqttException {
        //ProducePlan producePlan=producePlanService.selectByInfo(null,null,null,null,null);
        SerialNumber serialNumber=serialNumberService.select("producePlan");
        String result="001";
        SerialNumber serialNumber1=new SerialNumber();
        if(serialNumber!=null){
            if(Util.checkTime(serialNumber.getUpdatetime())){
                //String[] str=serialNumber.getSerialnum().split("-");
                int num = Integer.parseInt(serialNumber.getSerialnum());
                num++;
                result = String.format("%03d", num);
                serialNumber1.setId(serialNumber.getId());
            }

        }
        serialNumber1.setSerialnum(result);
        serialNumber1.setUpdatetime(Util.getNowTime());
        serialNumber1.setType("producePlan");
        if(serialNumber!=null){
            serialNumber1.setId(serialNumber.getId());
            serialNumberService.updateById(serialNumber1);
        }else{
            serialNumberService.save(serialNumber1);
        }

        return new GetMessage("成功","200","KVPC-"+Util.getNowTimeStr()+"-"+result);
    }
    @CrossOrigin(origins ="*" ,maxAge = 3600)
    @GetMapping("/finish")
    public GetMessage finish (String userId,String trainingId) throws JsonProcessingException, MqttException {
        PurchaseOrder purchaseOrder=purchaseOrderService.selectByInfo(userId,trainingId,null,null,"0");
        ProducePlan producePlan=producePlanService.selectByInfo(null,null,null,purchaseOrder.getOrdernumber(),null);
        ProducePlan p=producePlan;
        p.setProducenumber(purchaseOrder.getGoodsnumber());
        producePlanService.updateById(p);
        return new GetMessage("成功","200","");
    }
}
